package com.cono.markup

import com.cono.cvt.convertStructure
import java.util.*


typealias Document = ArrayList<Structure>

interface Structure{
    fun getData():String
}

class Heading(private val data: String) : Structure {
    override fun getData(): String {
       return data
    }
}

 class Paragraph(private val data: String) : Structure {
    override fun getData(): String {
        return data
    }
}

 class UnorderedList(val data: ArrayList<String>) : Structure {
    override fun getData(): String {
        return data.joinToString("\n")
    }
}

 class OrderList(val data: ArrayList<String>) : Structure {
    override fun getData(): String {
        return data.joinToString("\n")
    }
}

 class UnOrderedListItem(private val data: String) : Structure {
    override fun getData(): String {
        return data
    }
}


 class CodeBlock(val data: ArrayList<String>) : Structure {
    override fun getData(): String {
        return data.joinToString("\n")
    }
}

 class CodeBlockOpen(private val data: String) : Structure {
    override fun getData(): String {
        return data
    }
}

 class CodeBlockClose(private val data: String) : Structure {
    override fun getData(): String {
        return data
    }
}


open class Either(a: Any?, b: Any?)

class Left(a: Any) : Either(a, null)
class Right(b: Any) : Either(null, b)

fun parse(txts: ArrayList<String>): Document {

    val doc: Document = ArrayList()

    parseLines(doc, Optional.empty(), txts)
    return doc
}

val codeBlockOpenList = listOf("```java", "```kotlin", "```js")


fun parseLine(line: String): Structure {
    val ret: Structure

    if (codeBlockOpenList.contains(line)) {
        ret = CodeBlockOpen(line)
    } else if (line == "```") {
        ret = CodeBlockClose(line)
    } else if (line.startsWith("- ")) {
        ret = UnOrderedListItem(line)
    } else if (line.startsWith("* ")) {
        ret = Heading(line)
    } else {
        ret = Paragraph(line)
    }
    return ret
}


fun parseLines(doc: Document, context: Optional<Structure>, txts: MutableList<String>) {

    if (txts.size == 0) {
        return
    }
    val currentLine = txts.firstOrNull()
    currentLine?.let {
        val line = it.trim()
        val rest = txts.drop(1).toMutableList()
        if (line == "") {
            parseLines(doc, context, rest)
        } else {
            val item = parseLine(line)
            if (context.isEmpty) {
                doc.add(item)
                parseLines(doc, Optional.of(item), rest)
            } else {
                val ctx = context.get()
                if (item is CodeBlockClose) {
                    val temp = Paragraph("")
                    doc.add(temp)
                    parseLines(doc, Optional.of(temp), rest)
                } else {
                    if (ctx is CodeBlock) {
                        ctx.data.add(item.getData())
                        parseLines(doc,context,rest)
                    } else {
                        when (item) {
                            is UnOrderedListItem -> {
                                when (ctx) {
                                    is OrderList -> {
                                        ctx.data.add(item.getData())
                                    }

                                    is UnorderedList -> {
                                        ctx.data.add(item.getData())
                                    }

                                    else -> {
                                        val ol = OrderList(arrayListOf(item.getData()))
                                        doc.add(ol)
                                        parseLines(doc, Optional.of(ol), rest)
                                    }
                                }
                            }

                            is CodeBlockOpen -> {
                                val temp = CodeBlock(arrayListOf())
                                doc.add(temp)
                                parseLines(doc, Optional.of(temp), rest)
                            }

                            else -> {
                                doc.add(item)
                                parseLines(doc, Optional.of(item), rest)
                            }

                        }
                    }
                }
            }
        }
    }
}

fun main() {
    val doc = parse(
        arrayListOf(
            "- 1231231",
            "- asdadsas",
            "```java",
            "- asdads",
            "asdasdasd",
            "```",
            "* asdasdad"
        )
    )
    val j = 1

}